package com.zhengyisky.controller;

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.extension.api.R;
import com.zhengyisky.feign.UserClient;
import com.zhengyisky.pojo.*;
import com.zhengyisky.service.PurchaseService;
import com.zhengyisky.utils.OSSFileUtil;
import com.zhengyisky.utils.Result;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.amqp.AmqpException;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessagePostProcessor;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.messaging.handler.annotation.Header;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/purchase")
@Slf4j
public class PurchaseController {

    @Autowired
    private PurchaseService purchaseService;

    @Value("${jwt.privateKey}")
    private String privateKey;

    @Autowired
    private OSSFileUtil ossFileUtil;

    @Autowired
    private RabbitTemplate rabbitTemplate;

    @Autowired
    private UserClient userClient;

    @Autowired
    private RedissonClient redissonClient;

    @GetMapping("/company/list")
    public Result companyList(){
        List<Company> list = purchaseService.findAllCompany();
        return Result.success(list);
    }

    @GetMapping("/project/list")
    public Result projectList(){
        List<Project> list = purchaseService.findAllProject();
        return Result.success(list);
    }

    @GetMapping("/goods/listAll")
    public Result goodsListAll() {
        List<Goods> list = purchaseService.findAllGoods();
        return Result.success(list);
    }

    @GetMapping("/goods/list")
    public Result goodsList(){
        List<Goods> list = purchaseService.findAllGoods();

        List<Goods> resultList = new ArrayList<>();

        Map<Integer, Goods> map = new HashMap<>();

        for (Goods goods : list) {
            map.put(goods.getId(), goods);
        }

        for (Goods goods : list) {
            if(goods.getPid() == 0){
                resultList.add(goods);
            }else{
                Integer pid = goods.getPid();
                Goods parent = map.get(pid);

                List<Goods> children = parent.getChildren();
                if(children == null){
                    children = new ArrayList<>();
                    parent.setChildren(children);
                }
                children.add(goods);
            }
        }

        return Result.success(resultList);
    }

    @GetMapping("/type/list")
    public Result typeList(){
        List<Type> list = purchaseService.findAllType();
        return Result.success(list);
    }

    @GetMapping("/initForm")
    private Result initForm(HttpServletRequest request){
        String token = request.getHeader("token");

        String orderId = "";
        for(int i=0 ; i<6; i++){
            orderId += RandomUtil.randomChar("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
        }
        orderId += System.currentTimeMillis();

        Claims claims = Jwts.parser().setSigningKey(privateKey).parseClaimsJws(token).getBody();
        String username = (String) claims.get("username");
        Integer id = (Integer) claims.get("id");

        Map result = new HashMap<>();
        result.put("id",id);
        result.put("username",username);
        result.put("orderId",orderId);
        return Result.success(result);
    }

    @PostMapping("/upload")
    public Result upload(MultipartFile file) throws IOException {
        String path = ossFileUtil.uploadFileByBreakingPoint(file);
        return Result.success(path);
    }

    @PostMapping("/save")
    public Result save(@RequestBody OrderEntity orderEntity) throws InterruptedException {
        String sumPrice = orderEntity.getOrder().getSumPrice();
        String prePrice = orderEntity.getOrder().getPrePrice();

        String reg = "^\\d+$";
        if(!sumPrice.matches(reg)){
            return Result.error("订单金额必须为数值类型");
        }
        if(!prePrice.matches(reg)){
            return Result.error("预付款金额必须为数值类型");
        }

        RLock lock = redissonClient.getLock("project:" + orderEntity.getOrder().getProjectId());
        boolean flag  = lock.tryLock(30, 30, TimeUnit.SECONDS);
        if(flag){
            try {
                //检测预算是否充足
                Project project = purchaseService.findProjectById(orderEntity.getOrder().getProjectId());
                if(project.getTotalMoney().intValue() < Integer.parseInt(sumPrice)){
                    //项目预算<订单总价
                    return Result.error("项目预算不足！");
                }
                Integer newTotalMoney = project.getTotalMoney().intValue() - Integer.parseInt(sumPrice);
                //更新项目预算
                purchaseService.updateProject(orderEntity.getOrder().getProjectId(), newTotalMoney);
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                lock.unlock();
            }

        }else{
            return Result.error("扣减预算失败！");
        }

        purchaseService.save(orderEntity);
        return Result.success();
    }

    @GetMapping("/list")
    public Result list(HttpServletRequest request){
        String token = request.getHeader("token");

        User info = userClient.getInfo(token);

        if(info == null){
            return Result.error("user服务出现异常，触发熔断");
        }


        List<Order> list = null;
        if(info.getDeptId() == 1){
            //采购部
            list = purchaseService.listByUser(info.getId());
        }else{
            //管理部
            list = purchaseService.listByStatus();
        }

        Map map = new HashMap();
        map.put("dept",info.getDeptId());
        map.put("list",list);

        return Result.success(map);
    }

    @PutMapping("/submitApprove/{id}")
    public Result submitApprove(@PathVariable Integer id){
        purchaseService.submitApprove(id);

        Order order = purchaseService.findOrderById(id);

        rabbitTemplate.convertAndSend("exchange-2112a","",order);


        log.info("创建延迟消息，当前时间:{}", new Date());
        rabbitTemplate.convertAndSend("delay-2112a", "", order, new MessagePostProcessor() {
            @Override
            public Message postProcessMessage(Message message) throws AmqpException {
                message.getMessageProperties().setDelay(20000);
                return message;
            }
        });

        return Result.success();
    }

    @GetMapping("/find/{id}")
    public Result find(@PathVariable Integer id){
        OrderEntity entity = purchaseService.find(id);
        return Result.success(entity);
    }

    @PutMapping("/approve/{id}")
    public Result approve(@PathVariable Integer id,Integer status){
        purchaseService.approve(id,status);
        return Result.success();
    }
}
